function position(data) {
    return `(${num(data.x)},${num(data.y)})-(${num(data.x + data.width)},${num(data.y + data.height)})`;
}

function figure(info) {
    if (info.font) {
        return "Text";
    }

    if (info.image || info.type == "bitmap") {
        return "Image";
    }

    if ((info.fills && info.fills.length > 0)
        || (info.radius && info.radius.length > 0)
        || (info.borders && info.borders.length > 0)) {
        return "Container";
    }

    return "SizedBox";
}

function isGroup(cache) {
    return cache.type == "Stack" || cache.type == "Row" || cache.type == "Column";
}

function getTypeOption(type, subType) {
    let list = [];
    if (type == "Image") {
        subType = subType || "Image";
        let types = ["Image", "FLImage", "CachedNetworkImage"];
        types = types.filter((item) => {
            return item != subType
        })

        list.push(getOption(subType));
        for (let i = 0; i < types.length; i++) {
            list.push(getOption(types[i]));
        }
    } else if (type == "Text") {
        subType = subType || "Text";
        let types = ["Text", "TextField"];
        types = types.filter((item) => {
            return item != subType
        })

        list.push(getOption(subType));
        for (let i = 0; i < types.length; i++) {
            list.push(getOption(types[i]));
        }
    } else if (type == "Stack") {
        list.push(getOption("Stack"));
        list.push(getOption("Row"));
        list.push(getOption("Column"));
    } else if (type == "Row") {
        list.push(getOption("Row"));
        list.push(getOption("Stack"));
        list.push(getOption("Column"))
    } else if (type == "Column") {
        list.push(getOption("Column"));
        list.push(getOption("Stack"));
        list.push(getOption("Row"))
    } else {
        list.push(getOption(type));
    }

    return list.join("\n");
}

function supposeLayout(selectDatas) {
    if (selectDatas.length == 0) {
        return "None";
    }

    if (selectDatas.length == 1) {
        let parent = getCache(selectDatas[0]).parent;
        return figure(parent.data);
    }

    for (let i = 0; i < selectDatas.length; i++) {
        for (let j = i + 1; j < selectDatas.length; j++) {
            if (isIntersect(selectDatas[i], selectDatas[j])) {
                return "Stack";
            }
        }
    }

    // 按照x轴排序
    let xSorts = selectDatas.toSorted(function (a, b) {
        return a.x - b.x
    })
    let intersect = false;
    let start = xSorts[0];
    for (let i = 1; i < xSorts.length; i++) {
        if (xSorts[i].x < start.x + start.width) {
            intersect = true;
            break;
        }
        start = xSorts[i];
    }

    if (!intersect) {
        return "Row"
    }

    // 按照y轴排序
    let ySorts = selectDatas.toSorted(function (a, b) {
        return a.y - b.y
    })
    intersect = false;
    start = ySorts[0];
    for (let i = 1; i < ySorts.length; i++) {
        if (ySorts[i].y < start.y + start.height) {
            intersect = true;
            break;
        }
        start = ySorts[i];
    }
    if (!intersect) {
        return "Column"
    }


    return "Stack";
}

function isParent(parent, child) {
    if (child.level == 0 || parent.id == child.id) {
        return false;
    }
    if (parent.type == "Image" || parent.type == "Text") {
        return false;
    }
    if (child.children && child.children.length > 0) {
        for (let i = 0; i < child.children.length; i++) {
            if (child.children[i].id == parent.id) {
                return false;
            }
        }
    }
    let res = parent.x <= child.x
        && parent.y <= child.y
        && parent.x + parent.width >= child.x + child.width
        && parent.y + parent.height >= child.y + child.height;
    return res;
}

function extract(cacheList) {
    for (var i = 0; i < cacheList.length; i++) {
        var cache = cacheList[i];
        const { visibility, image, text, color, border, gradient } = diff;
    }
}

function findParent(cache, dataList) {
    let data = cache.data;
    let tmpList = [];
    for (var i = 0; i < dataList.length; i++) {
        let other = dataList[i];
        let otherCache = getCache(other);
        if (isParent(other, data) && cache.index > otherCache.index) {
            tmpList.push(other);
        }
    }

    // 找出最小的
    if (tmpList.length > 0) {
        let minParent = tmpList[0];
        let area = minParent.width * minParent.height;
        for (var i = 1; i < tmpList.length; i++) {
            let other = tmpList[i];
            let otherArea = other.width * other.height;
            if (area > otherArea) {
                minParent = other;
            } else if (area == otherArea) {
                if (figure(other) == "Container") {
                    minParent = other;
                    console.log("found parent with same area but Container");
                }
            }
        }
        return minParent;
    }

    return null;
}

function findChild(cache, dataList) {
    let data = cache.data;
    let children = [];

    for (var i = 0; i < dataList.length; i++) {
        if (isParent(data, dataList[i])) {
            let child = getCache(dataList[i]);
            if (!child.parent && cache.index < child.index) {
                children.push(dataList[i]);
            }
        }
    }

    return children;
}


function batchFindChild(cacheList) {
    let result = [];
    for (var i = 0; i < cacheList.length; i++) {
        let children = findChild(cacheList[i], cacheList);
        if (children.length > 0) {
            result.push(...children);
        }
    }
    return result;
}

function isIntersect(aData, bData) {
    // 矩形1的左上角和右下角坐标
    var x1 = aData.x;
    var y1 = aData.y;
    var x2 = aData.x + aData.width;
    var y2 = aData.y + aData.height;

    // 矩形2的左上角和右下角坐标
    var x3 = bData.x;
    var y3 = bData.y;
    var x4 = bData.x + bData.width;
    var y4 = bData.y + bData.height;

    // 如果一个矩形的右边缘在另一个矩形的左边缘右侧，或者一个矩形的下边缘在另一个矩形的上边缘下方，
    // 则这两个矩形不相交。
    if (x2 < x3 || x4 < x1 || y2 < y3 || y4 < y1) {
        return false;
    } else {
        return true; // 否则，矩形相交
    }
}

function isXIntersect(aData, bData) {
    return (aData.x >= bData.x && aData.x <= bData.x + bData.width) || (bData.x >= aData.x && bData.x <= aData.x + aData.width);
}

function isYIntersect(aData, bData) {
    return (aData.y >= bData.y && aData.y <= bData.y + bData.height) || (bData.y >= aData.y && bData.y <= aData.y + aData.height);
}

function findBiggest(selectList) {
    let res = selectList[0];
    for (let i = 1; i < selectList.length; i++) {
        if (selectList[i].width * selectList[i].height > res.width * res.height) {
            res = selectList[i];
        }
    }
    return res;
}

function guid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function fixLayoutSize(virtual) {
    let x, y, width, height;
    virtual.children.forEach(function (item) {
        let data = item.data;
        x = x ? Math.min(x, data.x) : data.x;
        y = y ? Math.min(y, data.y) : data.y;
        width = width ? Math.max(width, data.x + data.width) : data.x + data.width;
        height = height ? Math.max(height, data.y + data.height) : data.y + data.height;
    });
    virtual.data.x = x;
    virtual.data.y = y;
    virtual.data.width = width - x;
    virtual.data.height = height - y;
    console.log("cal layout size: ", virtual.data);
}

function mergeGroup(cache, other) {
    let data = cache.data;
    let otherData = other.data;
    genRelative(cache);
    genRelative(other);

    let offsetX;
    let offsetY;
    while (true) {

    }

    // if (data.x == otherData.x) {

    // } else if (data.y == otherData.y) {

    // }
}

function genRelative(cache) {
    let xSorts = cache.children.toSorted(function (a, b) {
        return a.data.x - b.data.x
    });

    let ySorts = cache.children.toSorted(function (a, b) {
        return a.data.y - b.data.y
    });

    let zSorts = cache.children.toSorted(function (a, b) {
        return a.data.index - b.data.index
    });

    cache.children.forEach(function (item) {
        let data = item.data;
        let offsetX = data.x - cache.data.x;
        let offsetY = data.y - cache.data.y;
        let xIndex = xSorts.indexOf(item);
        let yIndex = ySorts.indexOf(item);
        let zIndex = zSorts.indexOf(item);
        item.relative = {
            x: xIndex,
            y: yIndex,
            z: zIndex,
            offsetX: offsetX,
            offsetY: offsetY
        }
    });
}

function newVirtual() {
    let virtual = {
        isVirtual: true,
        data: {},
        id: guid()
    }

    virtual.data.id = virtual.id;

    customCache[virtual.id] = virtual;
    virtualMap[virtual.id] = virtual;
    return virtual;
}

function calculateOverlap(aData, bData) {
    // 计算每个矩形的右边界和下边界
    const aDataRight = aData.left + aData.width;
    const aDataBottom = aData.top + aData.height;
    const bDataRight = bData.left + bData.width;
    const bDataBottom = bData.top + bData.height;
  
    // 判断水平方向上的重叠
    const horizontalOverlapStart = Math.max(aData.left, bData.left);
    const horizontalOverlapEnd = Math.min(aDataRight, bDataRight);
    const horizontalOverlapWidth = horizontalOverlapEnd - horizontalOverlapStart;
  
    // 判断垂直方向上的重叠
    const verticalOverlapStart = Math.max(aData.top, bData.top);
    const verticalOverlapEnd = Math.min(aDataBottom, bDataBottom);
    const verticalOverlapHeight = verticalOverlapEnd - verticalOverlapStart;
  
    // 如果在任一方向上没有重叠，则重叠面积为0
    if (horizontalOverlapWidth <= 0 || verticalOverlapHeight <= 0) {
      return 0;
    }
  
    // 计算重叠面积
    return horizontalOverlapWidth * verticalOverlapHeight;
  }